﻿
using System;
using System.Collections;
using NUnit.Framework;

namespace RenewalProjects.Libraries.ParamGate.Tests
{
	[TestFixture]
	public class ParameterNavigatorFixture
	{
		[Test]
		public void Navigates_Basic_Parameter_List()
		{
			string[] testParams = new string[] { "-Name", "Danny", "-Holds", "Item A", "Item B" };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.AreEqual("Name", nav.Key);
			Assert.AreEqual(1, nav.Values.Count);
			Assert.AreEqual("Danny", nav.Values[0]);

			Assert.IsTrue(nav.MoveNext());
			Assert.AreEqual("Holds", nav.Key);
			Assert.AreEqual(2, nav.Values.Count);
			Assert.AreEqual("Item A", nav.Values[0]);
			Assert.AreEqual("Item B", nav.Values[1]);

			Assert.IsFalse(nav.MoveNext());
			Assert.IsNull(nav.Key);

			Assert.IsNull(nav.Values);
		}

		[Test]
		public void Navigates_A_Single_Key_Parameter()
		{
			string[] testParams = new string[] { "-SingleParam" };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.AreEqual("SingleParam", nav.Key);
			Assert.IsNotNull(nav.Values);
			Assert.IsEmpty((ICollection)nav.Values);

			Assert.IsFalse(nav.MoveNext());
		}

		[Test]
		public void Navigates_Multiple_Keys()
		{
			string[] testParams = new string[] { "-Key1", "-Key2", "-Key3" };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.AreEqual("Key1", nav.Key);
			Assert.IsNotNull(nav.Values);
			Assert.IsEmpty((ICollection)nav.Values);

			Assert.IsTrue(nav.MoveNext());
			Assert.AreEqual("Key2", nav.Key);
			Assert.IsNotNull(nav.Values);
			Assert.IsEmpty((ICollection)nav.Values);

			Assert.IsTrue(nav.MoveNext());
			Assert.AreEqual("Key3", nav.Key);
			Assert.IsNotNull(nav.Values);
			Assert.IsEmpty((ICollection)nav.Values);

			Assert.IsFalse(nav.MoveNext());
		}

		[Test]
		public void Navigates_Single_Value()
		{
			string[] testParams = new string[] { "Value" };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.IsNull(nav.Key);
			Assert.IsNotNull((ICollection)nav.Values);
			Assert.AreEqual(1, nav.Values.Count);
			Assert.AreEqual("Value", nav.Values[0]);

			Assert.IsFalse(nav.MoveNext());
		}

		[Test]
		public void Navigates_Multiple_Values()
		{
			string[] testParams = new string[] { "Value 1", "Value 2", "Value 3" };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.IsNull(nav.Key);
			Assert.IsNotNull((ICollection)nav.Values);
			Assert.AreEqual(3, nav.Values.Count);
			Assert.AreEqual("Value 1", nav.Values[0]);
			Assert.AreEqual("Value 2", nav.Values[1]);
			Assert.AreEqual("Value 3", nav.Values[2]);

			Assert.IsFalse(nav.MoveNext());
		}

		[Test]
		public void Navigates_Values_Before_A_Final_Key()
		{
			string[] testParams = new string[] { "Value 1", "Value 2", "Value 3", "-Final Key" };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.IsNull(nav.Key);
			Assert.IsNotNull((ICollection)nav.Values);
			Assert.AreEqual(3, nav.Values.Count);
			Assert.AreEqual("Value 1", nav.Values[0]);
			Assert.AreEqual("Value 2", nav.Values[1]);
			Assert.AreEqual("Value 3", nav.Values[2]);

			Assert.IsTrue(nav.MoveNext());
			Assert.AreEqual("Final Key", nav.Key);
			Assert.IsNotNull(nav.Values);
			Assert.IsEmpty((ICollection)nav.Values);

			Assert.IsFalse(nav.MoveNext());
		}

		[Test]
		public void Navigates_Empty_Parameter_List()
		{
			string[] testParams = new string[] { };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsFalse(nav.MoveNext());
			Assert.IsNull(nav.Key);
			Assert.IsNull(nav.Values);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Does_Not_Accept_Null_Parameter_List()
		{
			ParameterNavigator nav = new ParameterNavigator(null);
		}

		[Test]
		public void Navigator_Tries_To_Move_Beyond_End()
		{
			string[] testParams = new string[] { "Item" };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.IsFalse(nav.MoveNext());
			Assert.IsFalse(nav.MoveNext());
			// Try 1 more just for good measure ;-)
			Assert.IsFalse(nav.MoveNext());
		}

		[Test]
		public void Navigator_Initial_Key_And_Values()
		{
			ParameterNavigator nav = new ParameterNavigator(new string[] {});
			Assert.IsNull(nav.Key);
			Assert.IsNull(nav.Values);
		}

		[Test]
		public void Navigates_One_Empty_String_Parameter_In_Parameter_List()
		{
			string[] testParams = new string[] { "" };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.IsNull(nav.Key);
			Assert.IsNotNull(nav.Values);
			Assert.IsNotEmpty((ICollection)nav.Values);
			Assert.AreEqual(1, nav.Values.Count);
			Assert.IsEmpty(nav.Values[0]);
		}

		[Test]
		public void Navigates_Nulls_Item_In_Parameter_List()
		{
			string[] testParams = new string[] { null, null };
			ParameterNavigator nav = new ParameterNavigator(testParams);

			Assert.IsTrue(nav.MoveNext());
			Assert.IsNull(nav.Key);
			Assert.IsNotNull(nav.Values);
			Assert.IsNotEmpty((ICollection)nav.Values);
			Assert.AreEqual(2, nav.Values.Count);
			Assert.IsNull(nav.Values[0]);
			Assert.IsNull(nav.Values[1]);

			Assert.IsFalse(nav.MoveNext());
		}
	}
}
